package cn.remex.db.utils.reflect;

import cn.remex.RemexConstants;
import cn.remex.db.utils.Assert;
import cn.remex.db.utils.CoreSvo;
import cn.remex.db.utils.Judgment;
import cn.remex.db.utils.StringHelper;
import cn.remex.db.utils.aop.DynamicProxy;
import cn.remex.db.utils.date.DateHelper;
import cn.remex.db.utils.exception.ServiceCode;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.Consumer;

//import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

/**
 * 本类的主要目的是封装{@link java.lang.reflect}反射机制的功能<br>
 * 主要采用了"map对"映射的方法进行的缓存，极大提供了反射的效率。
 *
 * @author Hengyang Liu
 * @since 2012-10-17
 */
public class ReflectUtil implements RemexConstants {

    final static private HashMap<Class<?>, HashMap<String, Field>> AllField = new HashMap<>();
    final static private HashMap<Class<?>, HashMap<String, List<Method>>> AllMethods = new HashMap<>();
    final static private HashMap<Class<?>, HashMap<String, Method>> AllGetter = new HashMap<>();
    final static private HashMap<Class<?>, HashMap<String, Method>> AllSetter = new HashMap<>();
    final static private HashMap<Type, Class<?>[]> ParameterClasses = new HashMap<>();
    final static private ArrayList<Class<?>> SimpleType = new ArrayList<>();
    final static private ArrayList<Class<?>> NumeralTypes = new ArrayList<>();


    private static class BeforeAdvice implements MethodBeforeAdvice {

        @Override
        public void before(Method method, Object[] args, Object target) {
            String name = method.getName();
            boolean isGet;
            if (((isGet = name.startsWith("get")) || name.startsWith("is"))
                    && method.getParameterTypes().length == 0) {
                Consumer<String> fieldNameConsumer = (Consumer) CoreSvo.valLocal(String.valueOf(target.hashCode()));
                if (null != fieldNameConsumer)
                    fieldNameConsumer.accept(StringHelper.lowerFirstLetter(name.substring(isGet ? 3 : 2)));
            }
        }
    }
    private static BeforeAdvice beforeAdvice =new BeforeAdvice();
//    private static AOPFactory AopBeanFactory = new AOPFactory(
//            new AOPCaller(null) {
//                private static final long serialVersionUID = 4420894044903576950L;
//
//                @Override
//                public Object intercept(final Object obj, final Method method, final Object[] args, final MethodProxy proxy) throws Throwable {
//                    // 查找
//                    String name = method.getName();
//                    boolean isGet;
//                    if (((isGet = name.startsWith("get")) || name.startsWith("is"))
//                            && method.getParameterTypes().length == 0) {// predicate
//                        // 中用get的方法来获得sql中需要操作的field
//                        Consumer fieldNameConsumer = (Consumer) CoreSvo.valLocal(String.valueOf(obj.hashCode()));
//                        if (null != fieldNameConsumer)
//                            fieldNameConsumer.accept(StringHelper.lowerFirstLetter(name.substring(isGet ? 3 : 2)));
//                        return null;
//                    }
//                    // 只是为了截获属性名称,不用真实的调用
//                    return proxy.invokeSuper(obj, args);
//                }
//            });
    private static Class<?> ModelableClass;
    private static boolean modelableSupport = false;
    private static Map<Method, Type> NoSuchSetter = new HashMap<>();

    static {
        NumeralTypes.add(int.class);
        NumeralTypes.add(long.class);
        NumeralTypes.add(double.class);
        NumeralTypes.add(float.class);
        NumeralTypes.add(short.class);
        NumeralTypes.add(Integer.class);
        NumeralTypes.add(Long.class);
        NumeralTypes.add(Double.class);
        NumeralTypes.add(Float.class);
        NumeralTypes.add(Short.class);

        SimpleType.addAll(NumeralTypes);
        SimpleType.add(boolean.class);
        SimpleType.add(char.class);
        SimpleType.add(byte.class);
        SimpleType.add(Boolean.class);
        SimpleType.add(Character.class);
        SimpleType.add(Byte.class);
        SimpleType.add(String.class);
        SimpleType.add(Date.class);


        try {
            ModelableClass = Class.forName("cn.remex.db.rsql.model.Modelable");
            modelableSupport = true;
        } catch (ClassNotFoundException e) {
            logger.warn("ReflectUtil没有找到Modelable类型，故无法提供相关功能! {}", e);
        }
    }

    /**
     * 获取hashCode
     * 是有顺序的，传参位置不同计算出的hashCode值也不同
     *
     * @param c1        类
     * @param c2        类
     * @param extraType 动态的参数，用于hash计算(可不传)
     * @return 三个参数的hashCode
     */
    public static String hashCodeWithOrder(Class<?> c1, Class<?> c2, String... extraType) {
        Class<?> clazz1 = null, clazz2 = null;
        try {
            clazz1 = Class.forName(StringHelper.getClassName(c1));
            clazz2 = Class.forName(StringHelper.getClassName(c2));
        } catch (ClassNotFoundException e) {
            // Never arrived here
            e.printStackTrace();
        }
        int hc1 = clazz1.hashCode(), hc2 = clazz2.hashCode();
        StringBuilder ret = new StringBuilder().append(hc1).append(hc2);
        if (extraType != null)
            for (String s : extraType) {
                ret.append(null == s ? 0 : s.hashCode());
            }
        else
            ret.append(0);
        return ret.toString();
    }

    /**
     * 对象转换为基础类型
     * 包括包装类 包括String,如果欲转换类型不为其中则抛出异常
     *
     * @param type         希望case成的目标类型。
     * @param o            需要case的对象
     * @param instanceArgs 如果在case过程中需要新建相关对象，则传入instanceArgs参数。[0]为构造方法运行的对象；[1]为构造方法;[2-]构造方法所需的参数列表
     * @return Object 返回转化后的类型
     * @since 20140620 lanchenghao 添加入参中type的类型检查 非合法类型则抛出异常
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static Object caseObject(final Type type, final Object o, final Object... instanceArgs) {
        if (null == o || o.getClass() == type) {
            //布尔值不能直接返回null
            if (null == o && (boolean.class.equals(type) || Boolean.class.equals(type))) {
                return false;
            } else {
                return o;
            }
        }

        /** 一下是类型不匹配时的操作 **/
        final Class<? extends Object> sc = o.getClass();
        if (type == String.class) {
            if (sc == String[].class) {
                final StringBuilder ret = new StringBuilder();
                for (final String v : (String[]) o) {
                    ret.append(v).append(",");
                }
                ret.deleteCharAt(ret.length() - 1);
                return ret.toString();
            } else {
                return o.toString();
            }
        } else if (type == String.class && o instanceof Date) {
            return DateHelper.formatDate(DateHelper.dateToLocalDate((Date) o));
        } else if (o.getClass().isArray() && !((Class<?>) type).isArray()) {//来源是数组，目标不是数组则，按此规则转化
            Object[] os = (Object[]) o;
            if (os.length == 1) {
                return caseObject(type, os[0]);
            } else
                throw new ReflectionException("无法将包含两个元素的数组转化为一个对象！CaseObject失败！");

        } else if (Class.class.isAssignableFrom(type.getClass()) && ((Class<?>) type).isAssignableFrom(o.getClass())) {  // 子类父类的关系，或代理类的关系
            return o;
        } else if (Enum.class.isAssignableFrom((Class<?>) type)) {
            return Judgment.nullOrBlank(o) ? null : Enum.valueOf((Class) type, String.valueOf(o));
        }
//		else if (isFileType((Class<?>)type) && o instanceof MultipartFile) {
//			if (InputStream.class.isAssignableFrom((Class<?>) type)) {
//				try {
//					return ((MultipartFile) o).getInputStream();
//				} catch (IOException e) {
//					throw new ReflectionException("MultipartFile转化为InputStream失败");
//				}
//			} else{
//				throw new ReflectionException("请使用MultipartFile或InputStream替代File");
//			}
//
//		}
        else if (o instanceof String && modelableSupport && ModelableClass.isAssignableFrom((Class<?>) type)) {//数据库类
            if (Judgment.nullOrBlank(o))
                return null;
            Object t;
            if (instanceArgs == null || instanceArgs.length == 0 || instanceArgs[0] == null) {
                t = invokeNewInstance((Class) type);
            } else {
                t = invokeMethod((Method) instanceArgs[1], instanceArgs[0], Arrays.copyOfRange(instanceArgs, 2, instanceArgs.length));
            }
            invokeSetter("id", t, o);
            return t;
        } else if (type == boolean.class || type == Boolean.class) {// boolean值比较特殊
            if (sc == boolean.class || sc == Boolean.class) return o;
            return "1".equals(o) || "on".equals(o) || "yes".equals(o)
                    || "true".equals(o) || "On".equals(o) || "Yes".equals(o)
                    || "True".equals(o) || "ON".equals(o) || "YES".equals(o)
                    || "TRUE".equals(o) || Boolean.parseBoolean(o.toString());
        } else if (type == int.class || type == Integer.class) {
            if (sc == int.class || sc == Integer.class) return o;
            final String str = o.toString();
            return Double.valueOf(str.equals("") ? "0" : str).intValue();
        } else if (type == double.class || type == Double.class) {
            if (sc == double.class || sc == Double.class) return o;
            final String str = o.toString();
            return Double.valueOf(str.equals("") ? "0" : str);
        } else if (type == long.class || type == Long.class) {
            if (sc == long.class || sc == Long.class) return o;
            final String str = o.toString();
            return Double.valueOf(str.equals("") ? "0" : str).longValue();
        } else if (type == float.class || type == Float.class) {
            if (sc == float.class || sc == Float.class) return o;
            final String str = o.toString();
            return Double.valueOf(str.equals("") ? "0" : str).floatValue();
        } else if (type == short.class || type == Short.class) {
            if (sc == short.class || sc == Short.class) return o;
            final String str = o.toString();
            return Double.valueOf(str.equals("") ? "0" : str).shortValue();
        } else if (type == byte.class || type == Byte.class) {
            if (sc == byte.class || sc == Byte.class) return o;
            final String str = o.toString();
            return Double.valueOf(str.equals("") ? "0" : str).byteValue();
        } else if (type == Date.class) {
            if (sc == long.class || sc == Long.class) {
                return new Date((long) o);
            } else {
                if (sc == String.class) {
                    return DateHelper.localDateTimeToDate(DateHelper.parse((String) o));
                } else {
                    return o;
                }
            }
        } else if (type == char.class || type == Character.class) {
            if (sc == char.class || sc == Character.class) return o;
            final String str = o.toString();
            if (str.length() == 0) {
                return 0;
            } else {
                return o.toString().toCharArray()[0];
            }
        } else {
            throw new ReflectionException("指定的类型不合法,应为基础类型/对象为类型的子类/接口的实现。");
        }
    }


    /**
     * 判断是否是简单类型八个基本+String+Enum
     * 如果传入类的class为8个基础类型之一则返回true 否则 false
     *
     * @param c 类
     * @return boolean
     * TODO 暂未用
     */
    public static boolean isSimpleType(final Class<?> c) {
        return SimpleType.contains(c) || Enum.class.isAssignableFrom(c) || Object.class == c;
    }

    /**
     * 判断是否是数字类型
     *
     * @param c 类
     * @return boolean 判断返回值
     * @see ReflectUtil#NumeralTypes 参考数字类型有哪些
     */
    public static boolean isNumeralType(final Class<?> c) {
        return NumeralTypes.contains(c);
    }


//	public static boolean isFileType(Class type) {
//		return File.class.isAssignableFrom(type)
//				|| InputStream.class.isAssignableFrom(type)
////				|| MultipartFile.class.isAssignableFrom(type)
//				;
//	}

    /**
     * 判断两个{@link Type}参数是否完全相等。
     * 以下情况则返回true <p>1.当都是Class&lt;?&gt;并且完全相等 <p>2.如果是{@link Map}、{@link List}、{@link Collection}等<br> ParameterizedTypeImpl,复杂类型则需RawType和ActualTypeArguments完全相等
     *
     * @param type1 传入类型1
     * @param type2 传入类型2
     * @return 以下情况则返回true <p>1.当都是Class&lt;?&gt;并且完全相等 <p>2.如果是{@link Map}、
     * TODO 未用
     */
    public static boolean evaluateEqual(final Type type1, final Type type2) {
        if (type1 instanceof Class<?> && type2 instanceof Class<?>
                && type1 == type2) {
            return true;
        } else {
            try {
                final Class<?> rt1 = (Class<?>) ReflectUtil.invokeMethod("getRawType", type1);
                final Class<?> rt2 = (Class<?>) ReflectUtil.invokeMethod("getRawType", type2);
                // 判断基础类型一致
                if (rt1 != rt2) {
                    return false;
                }
                // 判断泛型个数必须一致
                final Type[] at1 = (Type[]) ReflectUtil.getActualTypeArguments(type1);
                final Type[] at2 = (Type[]) ReflectUtil.getActualTypeArguments(type2);
                if (at1.length != at2.length) {
                    return false;
                }

                // 逐个比较泛型是否相等
                for (int i = 0; i < at1.length; i++) {
                    if (at1[i] != at2[i]) {
                        return false;
                    }
                }

                // 至此则基础类型和泛型均相等
                return true;
            } catch (Exception e) {
                return false;
            }
        }
    }

    /**
     * 执行方法
     *
     * @param methodName 对象方法名字符串。如getName
     * @param target     目标对象
     * @param args       对象参数列表
     * @return Object
     */
    public static Object invokeMethod(final String methodName, final Object target,
                                      final Object... args) {
        try {
            Class<?>[] parameterTypes = null;
            if (null != args) {
                ArrayList<Class<?>> parameterTypeArr = null;
                parameterTypeArr = new ArrayList<Class<?>>(4);
                for (Object arg : args) {
                    parameterTypeArr.add(arg.getClass());
                }
                parameterTypes = parameterTypeArr.toArray(new Class<?>[]{});
            }
            Method method = target.getClass().getMethod(methodName,
                    parameterTypes);
            return method.invoke(target, args);
        } catch (final Exception ex) {
            handleReflectionException(ex);
        }
        throw new IllegalStateException("Should never get here");
    }

    /**
     * 获取实际类型参数
     *
     * @param type 类型
     * @return 类型数组
     */
    public static Type[] getActualTypeArguments(Type type) {
        if (type instanceof ParameterizedType)
            return ((ParameterizedType) type).getActualTypeArguments();
        else
            return new Type[0];
//		return (Type[]) ReflectUtil.invokeMethod("getActualTypeArguments", type);
    }

    /*
     * 映射异常
     */
    public static void handleReflectionException(final Exception ex) {
        if (ex instanceof NoSuchMethodException) {
            throw new IllegalStateException("未找到此方法: " + ex.getMessage());
        }
        if (ex instanceof IllegalAccessException) {
            throw new IllegalStateException("无权访问此方法: " + ex.getMessage());
        }
        if (ex instanceof InvocationTargetException) {
            handleInvocationTargetException((InvocationTargetException) ex);
        }
        if (ex instanceof RuntimeException) {
            throw (RuntimeException) ex;
        }
        handleUnexpectedException(ex);
    }

    public static void handleInvocationTargetException(
            final InvocationTargetException ex) {
        rethrowRuntimeException(ex.getTargetException());
    }

    public static void handleUnexpectedException(final Throwable ex) {
        // Needs to avoid the chained constructor for JDK 1.4 compatibility.
        final IllegalStateException isex = new IllegalStateException(ex);
        throw isex;
    }

    /**
     * 抛出运行时异常
     *
     * @param ex 异常
     */
    public static void rethrowRuntimeException(final Throwable ex) {
        if (ex instanceof RuntimeException) {
            throw (RuntimeException) ex;
        }
        if (ex instanceof Error) {
            throw (Error) ex;
        }
        handleUnexpectedException(ex);
    }

    /**
     * 获取全部属性
     *
     * @param clazz 所要获取属性的类
     * @return 以类为key 属性map为value的集合
     */
    public static HashMap<String, Field> getAllFields(final Class<?> clazz) {
        HashMap<String, Field> fields = AllField.get(clazz);
        if (null != fields) {
            return fields;
        }

        fields = new HashMap<String, Field>();

        //递归获取父类的属性
        if (Object.class != clazz.getSuperclass()) {
            Class<?> sup = clazz.getSuperclass();
            HashMap<String, Field> supFields = getAllFields(sup);
            fields.putAll(supFields);
        }

        final Field[] AutualFields = clazz.getDeclaredFields();
        for (final Field f : AutualFields) {
            fields.put(f.getName(), f);
        }


        AllField.put(clazz, fields);

        return fields;
    }


    /**
     * 获取类所有属性的setter方法
     * 检索某类中所有的setter方法<br>返回所有setter方法映射表。
     * <br>包括从它父类继承过来的。 <br>在返回的映射表中，key是属性名称，如setName(String Name)的name,value为对应的setter方法
     *
     * @param clazz 类
     * @return 返回本类型的所有setter方法映射表
     */
    public static Map<String, Method> getAllSetters(final Class<?> clazz) {
        HashMap<String, Method> setters = AllSetter.get(clazz);
        if (null != setters) {
            return setters;
        }

        final Method[] methods = clazz.getMethods();
        setters = new HashMap<String, Method>();
        for (Method m : methods) {
            if (m.getName().startsWith("set")
                    && m.getGenericParameterTypes().length == 1
                    && m.getReturnType() == void.class) {
                String fieldName = StringHelper.lowerFirstLetter(m.getName().substring(3));
                if (null != getGetter(clazz, fieldName) && getGetter(clazz, fieldName).getReturnType() != m.getGenericParameterTypes()[0])//如果有getter，则根据getter的返回类型配置setter
                    try {
                        m = clazz.getMethod(m.getName(), getGetter(clazz, fieldName).getReturnType());
                    } catch (Exception e) {
                        logger.warn("在初始化{}时，没有找到与getter方法相匹配类型的set方法，这是一个重要提示。setter为{};getter为 {}", clazz.getName(), m.toGenericString(), getGetter(clazz, fieldName).toGenericString());
                    }
                setters.put(fieldName, m);
            }
        }

        AllSetter.put(clazz, setters);

        return setters;
    }

    /**
     * 获取参数类所有属性的getter方法
     * 检索对象中所有的get方法，其参数类型仅有一个即被检索的对象类型<br>返回本类型的所有get方法映射表。含boolean型结果的is方法，包括继承过来的。 结果为{@link Map}<br>其中，key是get方法所规范的属性名，如getName()的name,value为对应的{@link Method}
     *
     * @param clazz 类
     * @return 返回本类型的所有get方法映射表
     */
    public static Map<String, Method> getAllGetters(final Class<?> clazz) {
        HashMap<String, Method> getters = AllGetter.get(clazz);
        if (null != getters) {
            return getters;
        }

        final Method[] methods = clazz.getMethods();
        getters = new HashMap<String, Method>();
        for (final Method m : methods) {
            if (m.getGenericParameterTypes().length == 0) {
                if (m.getName().startsWith("get")) {
                    getters.put(StringHelper.lowerFirstLetter(m.getName()
                            .substring(3)), m);
                } else if (m.getName().startsWith("is")
                        && (m.getReturnType() == boolean.class || m
                        .getReturnType() == Boolean.class)) {
                    getters.put(StringHelper.lowerFirstLetter(m.getName()
                            .substring(2)), m);
                }
            }
        }

        AllGetter.put(clazz, getters);

        return getters;
    }

    /**
     * 获取单个属性对应的getter方法
     *
     * @param clazz     类
     * @param fieldName 属性名称
     * @return 返回类属性名称对应的get方法
     */
    public static Method getGetter(final Class<?> clazz, final String fieldName) {
        return getAllGetters(clazz).get(fieldName);
    }


    /**
     * 获取单个属性
     * 根据目标类和属性名称 获取该属性Field
     *
     * @param clazz     类
     * @param fieldName 属性名称
     * @return Field 返回fieldName对应的类的Field属性
     */
    public static Field getField(final Class<?> clazz, final String fieldName) {
        return getAllFields(clazz).get(fieldName);
    }

    /**
     * 根据类中的方法名及参数来获取准确的方法
     *
     * @param clazz            类
     * @param methodName       方法名称
     * @param parameterTypeArr parameterTypeArr
     * @return Method 返回方法名称对应的Method
     */
    public static Method getMethod(final Class<?> clazz, final String methodName, Class<?>... parameterTypeArr) {
        Method method = null;
        try {
            method = clazz.getMethod(methodName, parameterTypeArr);
        } catch (Exception e) {
            handleReflectionException(e);
        }
        return method;
    }

    /**
     * 获得List声明的对应的泛型类型
     *
     * @param type type
     * @return 泛型类型
     * TODO 未用
     */
    public static Class<?> getListActualType(final Type type) {
        return obtainParameterClasses(type)[0];
    }

    /**
     * 获得List声明的对应的泛型类型
     *
     * @param type 泛型类型
     * @return 泛型类型
     * TODO 未用
     */
    public static Class<?>[] obtainParameterClasses(final Type type) {
        try {
            Class<?>[] curParameterClasses = ParameterClasses.get(type);
            if (null != curParameterClasses) {
                return curParameterClasses;
            }//缓存中存在了

            final Type[] types = ReflectUtil.getActualTypeArguments(type);

            ArrayList<Class<?>> curParameterClassesList = new ArrayList<>();
            for (Type parameterType : types) {
                if (parameterType instanceof ParameterizedType) {
                    curParameterClassesList.add((Class<?>) ((ParameterizedType) parameterType).getRawType());
                } else {
                    curParameterClassesList.add((Class<?>) parameterType);
                }
            }

            curParameterClasses = curParameterClassesList.toArray(new Class[0]);
            ParameterClasses.put(type, curParameterClasses);
            return curParameterClasses;
        } catch (final Exception e) {
            handleUnexpectedException(e);
            return new Class[0]; // never arrive here
        }
    }

    /**
     * 获取单个属性对应的setter方法
     *
     * @param clazz     类
     * @param fieldName 属性名称
     * @return 返回类属性名称对应的set方法
     */
    public static Method getSetter(final Class<?> clazz, final String fieldName) {
        return getAllSetters(clazz).get(fieldName);
    }

    public static <T> T createAopBean(Class<T> beanClass) {
        return DynamicProxy.getProxy(beanClass,beforeAdvice);
//        return AopBeanFactory.getBean(beanClass);
    }

    public static void eachFieldWhenGet(Object o, Consumer aopBeanConsumer, Consumer<String> fieldNameConsumer) {
        Object aopBean;
        if (o instanceof Class) {
            aopBean =  DynamicProxy.getProxy((Class)o,beforeAdvice);
//            AopBeanFactory.getBean((Class) o);
        } else if (o.getClass().toString().indexOf("$$EnhancerByCGLIB$$") > 0) {
            try {
                aopBean = DynamicProxy.getProxy(Class.forName(StringHelper.getClassName(o.getClass())),beforeAdvice);
            } catch (ClassNotFoundException e) {
                throw new ReflectionException("为已是代理的类型产生一个用于捕获属性的AOPBEAN失败。");
            }
        } else {
            aopBean =  DynamicProxy.getProxy(o.getClass(),beforeAdvice);
        }
        CoreSvo.putLocal(String.valueOf(aopBean.hashCode()), fieldNameConsumer);

        aopBeanConsumer.accept(aopBean);

        CoreSvo.putLocal(String.valueOf(aopBean.hashCode()), null);

    }

    /**
     * 根据clazz调用默认的无参构造函数生成相对应实例
     *
     * @param clazz 所要生成实例的类
     * @param <T>   t
     * @return 返回该实例
     */
    public static <T> T invokeNewInstance(Class<T> clazz) {
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            throw new ReflectionException("该属性所对应的类没有默认构造函数，" + clazz.toString());
        }
    }

    /**
     * 根据属性名称调用get并返回值。
     *
     * @param fieldName java bean 的属性名称。将根据此属性的名称调用相对应的getter方法。
     * @param target    java bean的实例。
     * @return 返回
     */
    static public Object invokeGetter(final String fieldName, final Object target) {
        Method getter = ReflectUtil.getAllGetters(target.getClass()).get(fieldName);
        if (null == getter)
            throw new ReflectionException("目标" + target + "中没有该属性对应的getter：" + fieldName);
        return ReflectUtil.invokeMethod(getter, target);
    }

    /**
     * 执行方法
     * 用提供的参数在目标对象上调用具体的 {@link Method}<br>如果是静态{@link Method}， 目标对象可以为空
     * <code>null</code>。<br>
     * <p>
     * 抛出的异常将通过 {@link #handleReflectionException}处理。<br>
     *
     * @param method 需调用的方法
     * @param target 方法的目标实例，如果是静态方法可为空。
     * @param args   传参 (可以为 <code>null</code>)
     * @return 返回的结果
     */
    public static Object invokeMethod(final Method method, final Object target,
                                      final Object... args) {
        if (null == method)
            throw new ReflectionException("调用目标" + target + "的方法时，Method对象不能为空!");

        try {
            return method.invoke(target, args);
        } catch (final Exception ex) {
            handleReflectionException(ex);
        }
        throw new IllegalStateException("Should never get here");
    }

    /**
     * 根据属性名称调用Set方法
     *
     * @param fieldName 属性名称
     * @param target    该属性所属的对象
     * @param value     该属性的数据类型
     */
    static public void invokeSetter(final String fieldName, final Object target,
                                    final Object value) {
        Method setter = ReflectUtil.getAllSetters(target.getClass()).get(fieldName);
        if (null == setter)
            throw new ReflectionException("目标" + target + "中没有该属性对应的setter：" + fieldName);

        ReflectUtil.invokeMethod(setter, target, value);
    }


    public static void invokeSetterWithDefaultTypeCoventer(final Object dest,
                                                           String field, Object value) {
        invokeSetterWithDefaultTypeCoventer(dest, getSetter(dest.getClass(), field), value, null);
    }

    /**
     * 调用setter方法对target赋值
     * 调用默认的类型转化器，将value转化为适当的类型后<br>
     *
     * @param setter 对象的setter方法
     * @param dest   目标对象
     * @param value  欲转换的value对象
     * @param status 附件功能
     */
    @SuppressWarnings({"unchecked"})
    public static void invokeSetterWithDefaultTypeCoventer(final Object dest,
                                                           Method setter, Object value, final ReflectFeatureStatus status) {
//		ReflectFeatureStatus status = new ReflectFeatureStatus(features);
        final Class<?> pt = setter.getParameterTypes()[0];
        //非空值的简单对象可以从子类向父类复制
        if ((null == status || !status.isSPFeatureOn) && null != value && isSimpleType(pt)) {
            invokeMethod(setter, dest, ReflectUtil.caseObject(pt, value));
            if (null != status && status.isDebugEnabled)
                logger.debug("SetValue: [{} with [{}] for ", setter.getName() + (setter.getName().length() < 15 ? "]\t\t" : "]\t"), value, dest.getClass().getSimpleName());
            return;
        }


        if (pt == String.class
                && (
                (status.ConvertNull2EmptyString && null == value)
                        || (status.ConvertZero2EmptyString && null != value && isNumeralType(value.getClass()) && (0 - Double.valueOf(value.toString())) == 0)
        )
                )
            value = "";

        /**
         * 如果不开启空字符串特性功能 默认将进行全值赋值 即不进行null-&gt;""转化，并无论value是何值，将覆盖dest相应的值。
         */
        if (pt == String.class && "".equals(value)
                && (null == status || status.IgnoreEmptyStringValue)
                ) {
            if (status.isDebugEnabled)
                logger.debug("SetValue: [{} ignore [EMPTYSTRING] for {}", setter.getName() + (setter.getName().length() < 15 ? "]\t\t" : "]\t"), dest.getClass().getSimpleName());
        } else {
            if (null != value || status.EnableNullValue) {
                if (NoSuchSetter.containsKey(setter) && null != value && NoSuchSetter.get(setter) == value.getClass()) {
                    logger.debug("-----目标对象 {}set方法无此重载：{}({})", dest, setter.getName(), value.getClass());
                    return;
                } else {
                    Object nValue;
                    //对简单对象和复杂对象进行分别得值预处理
                    if (isSimpleType(pt) ||
                            (!status.enableDeeplyCopy && !Collection.class.isAssignableFrom((Class<?>) pt) && !Map.class.isAssignableFrom((Class<?>) pt))
                            ) {
                        //简单对象case即可
                        nValue = ReflectUtil.caseObject(pt, value);
                    } else {
                        //复杂对象有三类：Map Collection Object

                        if (!status.enableDeeplyCopy) {
                            return;
                        }

                        if (Collection.class.isAssignableFrom(pt) && value instanceof Collection<?>) {//集合对象
						/* LHY 2014-9-25 深度复制时，collection目标对象完全被新collection中的对象替换而导致原始item值不可控的丢失。
						 * 本次修复，新增标志RemoveTargetGatherItemWhenSourceExclued，当它为true时删除源对象中没有的item，源和目标都有的则通过copy来复制
						Collection<Object> field = (Collection<Object>) invokeNewInstance(value.getClass());
						Type pt2 = setter.getGenericParameterTypes()[0];
						Class<?> targetItemClass = obtainCollectionRawType(pt2);
						for(Object item:(Collection<?>)value){
							if(null == item)continue;
							Object itemNew = invokeNewInstance(targetItemClass);
							ReflectUtil.copyProperties(itemNew, item, status.features);
							field.add(itemNew);
						}
						*/
                            //以下内容为修复 2014-9-29
                            Collection<Object> field = (Collection<Object>) invokeGetter(StringHelper.lowerFirstLetter(setter.getName().substring(3)), dest);
                            if (null == field) field = (Collection<Object>) invokeNewInstance(value.getClass());
                            Type pt2 = setter.getGenericParameterTypes()[0];
                            Class<?> targetItemClass = obtainCollectionRawType(pt2);
                            Collection<Object> collection = (Collection<Object>) value;

                            //TODO 转化为数组进行匹配。Collection很难搞定。
                            Object[] arr_c = collection.toArray();
                            Object[] arr_f = field.toArray();
                            int arr_c_len = arr_c.length, arr_f_len = arr_f.length,
                                    max = arr_c_len > arr_f_len ? arr_c_len : arr_f_len;
                            boolean itemIsSimple = isSimpleType(targetItemClass) || Enum.class.isAssignableFrom(targetItemClass);
                            Object[] arr_f_new = new Object[max];
                            for (int i = 0; i < max; i++) {
                                if (i < arr_c_len && null != arr_c[i]) {//L1来源有元素
                                    if (!itemIsSimple) {    //L1.1非简单类型
                                        Object curItem = (i >= arr_f_len || null == arr_f[i]) ? invokeNewInstance(targetItemClass) : arr_f[i];
                                        ReflectUtil.copyProperties(curItem, arr_c[i], status.features);
                                        arr_f_new[i] = curItem;
                                    } else {                            //L1.2 简单类型
                                        arr_f_new[i] = arr_f[i];
                                    }
                                } else { //L2 来源没有元素
                                    if (i < arr_f_len && !status.RemoveTargetGatherItemWhenSourceExclude) {
                                        arr_f_new[i] = arr_f[i];
                                    } else {
                                        //此处删除元素或者不予赋值;
                                    }
                                }
                            }
                            field.clear();
                            for (Object item : arr_f_new) {
                                if (null != item)
                                    field.add(item);
                            }
                            //2014-9-29 end

                            value = field;//深度复制到是新的对象
                        } else if (Map.class.isAssignableFrom(pt) && value instanceof Map<?, ?>) {//Map对象
						/* LHY 2014-9-25 深度复制时，map目标对象完全被新map中的对象替换而导致原始item值不可控的丢失。
						 * 本次修复，新增标志RemoveTargetGatherItemWhenSourceExclued，当它为true时删除源对象中没有的item，源和目标都有的则通过copy来复制
						Map<Object,Object> field = (Map<Object,Object>) invokeNewInstance(value.getClass());
						Map<Object, Object> map = ((Map<Object,Object>) value);
						for(Object key:map.keySet()){
							Object item = map.get(key);
							if(null == item)continue;
							Object itemNew = invokeNewInstance(item.getClass());
							ReflectUtil.copyProperties(itemNew,item , status.features);
							field.put(key,itemNew);
						}
						*/
                            //以下内容为修复 2014-9-25
                            Map<Object, Object> field = (Map<Object, Object>) invokeGetter(StringHelper.lowerFirstLetter(setter.getName().substring(3)), dest);
                            if (null == field) field = (Map<Object, Object>) invokeNewInstance(value.getClass());
                            Map<Object, Object> map = ((Map<Object, Object>) value);
                            Type pt2 = setter.getGenericParameterTypes()[0];
                            Class<?> targetValueClass = (Class<?>) getActualTypeArguments(pt2)[1];
                            boolean valueIsSimple = isSimpleType(targetValueClass) || Enum.class.isAssignableFrom(targetValueClass);
                            for (Object key : map.keySet()) {
                                Object item_m = map.get(key);
                                Object item_f = field.get(key);

                                if (null == item_m && null == item_f) {
                                    continue;
                                } else if (null != item_m) {
                                    if (valueIsSimple) {
                                        item_f = item_m;
                                    } else {
                                        if (null == item_f) item_f = invokeNewInstance(targetValueClass);
                                        ReflectUtil.copyProperties(item_f, item_m, status.features);
                                    }
                                    field.put(key, item_f);
                                } else {
                                    throw new ReflectionException("深度复制时，map数据不符合规则！");
                                }
                            }
                            if (status.RemoveTargetGatherItemWhenSourceExclude) {//如果目标中的对象在来源中没有，则删除
                                List<Object> keys = new ArrayList<Object>();
                                for (Object key : field.keySet()) {
                                    if (!map.containsKey(key)) keys.add(key);
                                }
                                for (Object key : keys) field.remove(key);
                            }
                            //2014-9-25 end

                            value = field;//深度复制到是新的对象
                        } else {//普通Object对象
                            /**
                             * BUG号:
                             * 2014-04-17
                             * 深度复制中,原object 类型的属性值被置空的bug修复
                             *
                             Object object = null;

                             object = invokeNewInstance(pt);
                             *
                             *
                             * **/
                            Object object = invokeGetter(StringHelper.lowerFirstLetter(setter.getName().substring(3)), dest);    //从源对象中读取object属性是否为空
                            if (null == object)                                                                                        //为空时将初始化一个新对象。
                                object = invokeNewInstance(pt);
                            /***bug修复结束**/

                            ReflectUtil.copyProperties(object, value, status.features);
                            value = object;//深度复制到是新的对象
                        }// end for 复杂对象有三类：Map Collection Object

                        nValue = value;
                    }

                    try {
                        ReflectUtil.invokeMethod(setter, dest, nValue);
//					ReflectUtil.invokeMethod(setter, dest, ReflectUtil.caseObject(pt, value));
                    } catch (final IllegalArgumentException e) {
                        //如果setter有重载，在此处理
                        logger.warn("-----目标对象 {}set方法有重载：{}({})", dest, setter.getName(), setter.getParameterTypes()[0]);
                        try {
                            if (null != value) {
                                setter = dest.getClass().getMethod(setter.getName(), value.getClass());
                                //用常用的setter来更新缓存 TODO 将来需要做一个统计函数。
//							ReflectUtil.getAllSetters(dest.getClass()).put(StringHelper.lowerFirstLetter(setter.getName().substring(3)), setter);
                            }
                        } catch (final NoSuchMethodException e1) {
                            NoSuchSetter.put(setter, value.getClass());
                            logger.warn("-----目标对象 {}set方法中无法找到如此重载：{}({})", dest, setter.getName(), value.getClass());
                            //如果没有这个方法，说明类型不对不用设置
                            return;
                        }
                        ReflectUtil.invokeMethod(setter, dest, ReflectUtil.caseObject(pt, value));
                    }
                    if (status.isDebugEnabled)
                        logger.debug("SetValue [{} with [{}] for {}", setter.getName(), (setter.getName().length() < 15 ? "]\t\t" : "]\t"), value, dest.getClass().getSimpleName());
                }
            } else {
                if (status.isDebugEnabled)
                    logger.debug("SetValue: [ {} {} ignore [null] ]for{}", setter.getName(), (setter.getName().length() < 15 ? "]\t\t" : "]\t"), dest.getClass().getSimpleName());
            }
        }
    }

    /**
     * 从Type获取类名。
     * 凡是Class&lt;?&gt;可返回Class&lt;?&gt; 如果是Map、Set等的Type，则有RawType返回Class&lt;?&gt;
     *
     * @param type type
     * @return 相应类
     */
    public static Class<?> obtainClass(final Type type) {
        Class<?> clazz;
        if (type instanceof Class<?>) {
            clazz = (Class<?>) type;
        }
//		else if (type instanceof ParameterizedTypeImpl) {
//			final ParameterizedTypeImpl typeImpl = (ParameterizedTypeImpl) type;
//			clazz = typeImpl.getRawType();
//		} else {
//			return null;
//		}
        else {

            clazz = (Class<?>) invokeMethod("getRawType", type);
        }
        return clazz;
    }

    /**
     * 获取集合中实际元素的泛型类型
     *
     * @param type 类型
     * @return Class
     */
    public static Class<?> obtainCollectionRawType(final Type type) {
        Class<?> clazz;
//			if (type instanceof ParameterizedTypeImpl) {
//				final ParameterizedTypeImpl typeImpl = (ParameterizedTypeImpl) type;
//				clazz = (Class<?>) typeImpl.getActualTypeArguments()[0];
//			} else {
//				return null;
//			}

        clazz = (Class<?>) ReflectUtil.getListActualType(type);


        return clazz;
    }


    /**
     * 对象赋值
     * 将源对象中与目标对象属性名相同的值进行复制。 方向是源对象orig的属性值复制到目标对象相应属性的值<br>
     * 如果属性有映射，请列入methodMap中<br>
     *
     * @param target   目标对象
     * @param source   源对象
     * @param features features
     * @see SPFeature
     */
    public static void copyProperties(final Object target, final Object source, final SPFeature... features) {
        copyProperties(target, source,
                //TODO 测试完后使用第二段代码
				/*1.
				ReflectContextDefaultFactory.getFieldMap(target.getClass(), source.getClass()),//进行属性映射的时候，因为是根据目标对象的set方法进行配置值，所以targetKey是key
				ReflectContextDefaultFactory.getCodeMap(target.getClass(),source.getClass()),	//进行值映射的时候，因为只能拿到来源的code，所以sourceCode是key且其必须唯一,但方向依然是t-s
				/*/
                ReflectConfigure.obtainReflectContext(target.getClass(), source.getClass(), null, null),
                //*/
                features);
    }


    /**
     * 对象赋值
     *
     * @param target         目标对象
     * @param source         源对象
     * @param reflectContext 映射上下文
     * @param features       附件功能
     */
    private static void copyProperties(final Object target, final Object source,
                                       final ReflectContext reflectContext,
                                       final SPFeature... features) {
        if (logger.isDebugEnabled()) logger.debug("=====即将从源对象 {}查找与目标对象 {}set方法对应的get方法进行赋值。", source, target);
        Assert.notNull(target, ServiceCode.ERROR, "复制时目标对象不能为空");
        Assert.notNull(source, ServiceCode.ERROR, "复制时来源对象不能为空");
        Assert.isSimpleBean(target, ServiceCode.ERROR, "复制时目标对象必须是简单的Object对象，不能为Map或者Collection！");
        Assert.isSimpleBean(source, ServiceCode.ERROR, "复制时来源对象必须是简单的Object对象，不能为Map或者Collection！");

        ReflectFeatureStatus status = new ReflectFeatureStatus(features);
        status.enableMethodMap = reflectContext.enableFieldMap;
        Map<String, String> methodMap = status.enableMethodMap ? reflectContext.getFieldMap() : null;
        status.enableCodeMap = reflectContext.enableCodeMap;
        Map<String, Map<String, String>> codeMap = status.enableCodeMap ? reflectContext.getCodeMap() : null;

        final Map<String, Method> origGetters = getAllGetters(source.getClass());
        Map<String, Method> destSetters = getAllSetters(target.getClass());

        //默认情况不对remex的ORMBeans的id，datastatus进行赋值
        if (!status.CopyIdAndDataStatus && modelableSupport && ModelableClass.isAssignableFrom(target.getClass())) {
            HashMap<String, Method> destSettersNoIdAndDataStatus = new HashMap<String, Method>();
            destSettersNoIdAndDataStatus.putAll(destSetters);
            destSettersNoIdAndDataStatus.remove("id");
            destSettersNoIdAndDataStatus.remove("dataStatus");
            destSetters = destSettersNoIdAndDataStatus;
        }

        // 赋值
        String getKey;
        for (final String setKey : destSetters.keySet()) {
            //默认情况get方法和set方法对应的属性名称是一致的。
            getKey = setKey;
            //如果有属性映射，则重新查找get方法对应的属性名称。
            if (status.enableMethodMap && methodMap.containsKey(setKey)) {
                getKey = methodMap.get(setKey);
            }


            // 赋值
            if (origGetters.containsKey(getKey)) {
                /**原来的代码效率略低*/
//				Object value = invokeGetter(getKey, source);
//				Method setter = getSetter(target.getClass(), setKey);
//				invokeSetterWithDefaultTypeCoventer(target, setter, value,
//						features);
                /**这是优化后的代码，直接从当前map获得method*/
                Object value = ReflectUtil.invokeMethod(origGetters.get(getKey), source);
                //如果有得了code映射，。
                if (status.enableCodeMap && codeMap.containsKey(setKey)) {
                    Object targetValue = codeMap.get(setKey).get(value);
                    if (null != targetValue) value = targetValue;
                }
                invokeSetterWithDefaultTypeCoventer(target, destSetters.get(setKey), value, status);
            } else {
                //if(logger.isDebugEnabled())logger.debug("-----set所需要的方法"+key+"不在源对象"+source+"中，赋值目标对象为"+target);
            }
        }
    }


    /**
     * 根据类中的方法名来搜索方法
     *
     * @param clazz      类
     * @param methodName 方法名称
     * @return 返回方法名称对应的Method
     */
    public static Method getMethod(final Class<?> clazz, final String methodName) {
        Method method = null;
        try {
            List<Method> methods = getAllMethods(clazz).get(methodName);
            if (null == methods || methods.size() == 0) return null;
            method = methods.get(0);
        } catch (Exception e) {
            handleReflectionException(e);
        }
        return method;
    }

    public static HashMap<String, List<Method>> getAllMethods(final Class<?> clazz) {
        HashMap<String, List<Method>> methods = AllMethods.get(clazz);
        if (null != methods) {
            return methods;
        }

        final Method[] methodArr = clazz.getMethods();
        methods = new HashMap<String, List<Method>>();
        for (final Method m : methodArr) {
            List<Method> ml = methods.get(m.getName());
            if (ml == null) {
                ml = new ArrayList<>();
                methods.put(m.getName(), ml);
            }
            if (!ml.contains(m)) ml.add(m);
        }

        AllMethods.put(clazz, methods);

        return methods;
    }

    static public <T extends Annotation> T getAnnotation(final Class<?> clazz, final Class<T> annotationClass) {
        return clazz.getAnnotation(annotationClass);
    }

    /**
     * 获取注解类
     * 根据getter，setter,field的顺序取查找annotationClass
     * <p>
     * LHY 2015-9-13 field必须是最后。因为子类可以通过重载方法(getter/setter)来正获取自定义的anno。
     *
     * @param <T>             t
     * @param annotationClass annotationClass
     * @param clazz           clazz
     * @param fieldName       fieldName
     * @return T
     */
    static public <T extends Annotation> T getAnnotation(final Class<?> clazz, final String fieldName, final Class<T> annotationClass) {
        T anno;
        Field f;
        Method m;
        f = ReflectUtil.getField(clazz, fieldName);
        m = ReflectUtil.getGetter(clazz, fieldName);
        if (null != m) {
            anno = m.getAnnotation(annotationClass);
            if (null != anno) {
                return anno;
            }
        }
        m = ReflectUtil.getSetter(clazz, fieldName);
        if (null != m) {
            anno = m.getAnnotation(annotationClass);
            if (null != anno) {
                return anno;
            }
        }
        if (null != f) {
            anno = f.getAnnotation(annotationClass);
            if (null != anno) {
                return anno;
            }
        }
        return null;

    }

    /**
     * SPFeature缩写自:SetPropertiesFeature<br>
     * 该枚举变量用于copyProperties，标识属性拷贝过程中的不同附加功能
     */
    public enum SPFeature {
        /**
         * 设置javabean 属性时，在需要String 参数的方法的入参为null时，转化为""
         */
        ConvertNull2EmptyString,
        /**
         * 设置javabean 属性时，在需要String 参数的方法的入参为0/0.0时，转化为""
         */
        ConvertZero2EmptyString,

        /**
         * 赋值时对null使用。比如从源对象A中通过getName获得值null，将赋值给B.setName(null)。
         * 此时原来B无论Name是否为null将被覆盖。
         * <p>
         * 此特性有效时将终止排在其后的其他特性
         */
        EnableNullValue,
        /**
         * 赋值时忽略空字符串,“”
         * <p>
         * 此特性有效时将终止排在其后的其他特性
         */
        IgnoreEmptyStringValue,

        /**
         * 仅仅只是用前缀名取值，即忽略非前缀取值。
         */
        JustUseNamePreffix,
        /**
         * 忽略属性或方法的大小写。
         */
        IgnoreCase,
        /**
         * 复制id and dataStatus
         */
        CopyIdAndDataStatus,
        /**
         * 复制id
         */
        CopyId,
        /**
         * 复制dataStatus
         */
        CopyDataStatus,
        /**
         * 深度复制，目前仅支持object/Collection/Map对象,即不允许直接被复制的两个对象为集合<br>
         * <font style='color:red'>陷阱：如果被复制对象的任意属性或子属性 包含对自身的引用 调用该属性进行复制时会产生死循环</font>
         */
        DeeplyCopy,
        /**
         * 删除目标对象中map/collection中不存在于源对象的item.<br>
         * 规则：<br>
         * 1.如果目标map中的key不存在于源map，则删除<br>
         * 2.如果目标中的collection数量大于源，多出部分删除
         * 3.此功能必须开启DeeplyCopy
         * 4.默认情况下，不删除。
         */
        RemoveTargetGatherItemWhenSourceExclude
    }

}
